package suncertify.remoting;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import suncertify.application.ApplicationMode;
import suncertify.contractors.Contractor;
import suncertify.contractors.ContractorsAccess;
import suncertify.contractors.ContractorsAccessImpl;
import suncertify.contractors.exceptions.CloseContractorsException;
import suncertify.contractors.exceptions.ContractorFindException;
import suncertify.contractors.exceptions.ContractorUpdateException;
import suncertify.contractors.exceptions.ContractorsInitializationException;
import suncertify.contractors.exceptions.ReadAllContractorsException;

/**
 * Provides a remote implementation of the {@link ContractorsAccess} interface. This class makes the
 * {@link ContractorsAccess} methods accessible from virtual machines that run on remote computers. This class
 * encapsulates and uses one instance of the {@link ContractorsAccessImpl} class, all methods of this class simply
 * delegate the calls to the corresponding methods in the {@link ContractorsAccessImpl} class.
 * 
 * <p>
 * This class is instantiated when the application is started in the {@link ApplicationMode#SERVER}, in this mode one
 * instance of this class is created, all remote method calls that come from client applications on remote machines are
 * Forwarded to the corresponding methods in this class.
 * 
 * <p>
 * All method calls in this class are simply forwarded to the corresponding method in the {@link ContractorsAccessImpl}
 * class that is created in the constructor, all method parameters are passed as they are without any validation, all
 * return values are returned as they are without any validation.
 * 
 * @see UnicastRemoteObject
 * @see RemoteContractorsAccess
 */
public class RemoteContractorsAccessImpl extends UnicastRemoteObject implements RemoteContractorsAccess {

    /**
     * Automatically generated serialization version ID.
     */
    private static final long serialVersionUID = 8719770485900167738L;

    /**
     * Declares the {@link ContractorsAccessImpl} reference.
     */
    private suncertify.contractors.ContractorsAccessImpl contractors;

    /**
     * Constructs the class with the provided parameter. The constructor uses the <code>filePath</code> parameter to
     * create one instance of the {@link ContractorsAccessImpl} class, the reference to this instance is saved in a
     * private class variable.
     * 
     * @param filePath
     *            The path to the applications database file.
     * @throws ContractorsInitializationException
     *             See {@link ContractorsAccessImpl}
     * @throws RemoteException
     *             For any remote communication errors, see {@link RemoteException}
     * 
     * @throws IllegalArgumentException
     *             If the <code>filePath</code> is null.
     * 
     */
    public RemoteContractorsAccessImpl(String filePath) throws ContractorsInitializationException, RemoteException {

	if (filePath == null) {
	    throw new IllegalArgumentException(
		    "RemoteContractorsAccessImpl cannot be constructed with a null filePath parameter.");
	}

	this.contractors = new suncertify.contractors.ContractorsAccessImpl(filePath);
    }

    /**
     * Simply passes the parameters to {@link ContractorsAccessImpl#findByCriteria(String[])} method of the
     * {@link ContractorsAccessImpl} object created in the constructor.
     * 
     * @param criteria
     *            See {@link ContractorsAccessImpl#findByCriteria(String[])}.
     * @return Returns the contractors from {@link ContractorsAccessImpl#findByCriteria(String[])} to the remote client.
     * @throws ContractorFindException
     *             See {@link ContractorsAccessImpl#findByCriteria(String[])}.
     * @throws RemoteException
     *             For any remote communication errors, see {@link RemoteException}
     * 
     */
    public Contractor[] findByCriteria(String[] criteria) throws ContractorFindException, RemoteException {

	return this.contractors.findByCriteria(criteria);
    }

    /**
     * Simply calls {@link ContractorsAccessImpl#getAllContractors()} method of the {@link ContractorsAccessImpl} object
     * created in the constructor.
     * 
     * @return See {@link ContractorsAccessImpl#getAllContractors()}.
     * @throws ReadAllContractorsException
     *             See {@link ContractorsAccessImpl#getAllContractors()}.
     * @throws RemoteException
     *             For any remote communication errors, see {@link RemoteException}
     * 
     */
    public Contractor[] getAllContractors() throws ReadAllContractorsException, RemoteException {

	return this.contractors.getAllContractors();
    }

    /**
     * Simply calls {@link ContractorsAccessImpl#updateContractor(Contractor)} method of the
     * {@link ContractorsAccessImpl} object created in the constructor with the provided parameter.
     * 
     * @param newContractor
     *            See {@link ContractorsAccessImpl#updateContractor(Contractor)}
     * @throws ContractorUpdateException
     *             Thrown if the update contractor fails due to any exceptions.
     * @throws RemoteException
     *             For any remote communication errors, see {@link RemoteException}
     * 
     */
    public void updateContractor(Contractor newContractor) throws ContractorUpdateException, RemoteException {

	this.contractors.updateContractor(newContractor);
    }

    /**
     * Simply calls {@link ContractorsAccessImpl#closeContractors()} method of the {@link ContractorsAccessImpl} object
     * created in the constructor.
     * 
     * @throws CloseContractorsException
     *             See {@link ContractorsAccessImpl#closeContractors()}
     * @throws RemoteException
     *             For any remote communication errors, see {@link RemoteException}
     * 
     */
    public void closeContractors() throws CloseContractorsException, RemoteException {

	this.contractors.closeContractors();
    }
}
